#include "client.h"
#include "environment.h"
#include "led.h"
#include "screen.h"
#include "smoke.h"
#include "ultrasonic.h"
#include "word.h"
#include <fcntl.h>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

using namespace std;

#define LED_DEV ("/dev/fb0")

typedef struct tagPARKINGLOT {
    char lamp[2];          // 灯 1 0x1
    char railing[2];       // 栏杆 1 0x2
    char camera[2];        // 摄像头 1 0x3
    char distance[3];      // 距离 2 0x4
    char temperature[3];   // 温度 2 0x5
    char humidity[3];      // 湿度 2 0x6
    char altitude[3];      // 海拔 2 0x7
    char pressure[5];      // 气压 4 0x8
    char concentration[3]; // 烟雾浓度 2 0x9
    char threshold[3];     // 烟雾阈值 2 0xa
    char illumination[5];  // 光照强度 4 0xb
    char total[5];         // 车位总数 4 0xc
    char remainder[5];     // 车位剩余 4 0xd
} PARKINGLOT, *HPARKINGLOT;

static void copy(char *dest, const int src, const int size) {
    int i;
    for (i = size - 1; i >= 0; i--)
        dest[i] = src >> (i * 8) & 0x000000ff;
}

static int32_t stoi(char str[]) {
    int32_t i, num = 0, len = strlen(str);
    for (i = 0; i < len; i++) {
        num *= 10;
        num += str[i] - 48;
    }
    return num;
}

static uint32_t signal = 1;
static PARKINGLOT parkinglot = {0};

void *main_thread(void *argv) {
    Client *client = (Client *)argv;
    // 循环发送数据
    while (signal) {
        // 发送灯
        client->write_data(vector< uint8_t >(parkinglot.lamp, parkinglot.lamp + sizeof(parkinglot.lamp)));
        // 发送栏杆
        client->write_data(vector< uint8_t >(parkinglot.railing, parkinglot.railing + sizeof(parkinglot.railing)));
        // 发送摄像头
        client->write_data(vector< uint8_t >(parkinglot.camera, parkinglot.camera + sizeof(parkinglot.camera)));
        // 发送距离
        client->write_data(vector< uint8_t >(parkinglot.distance, parkinglot.distance + sizeof(parkinglot.distance)));
        // 发送温度
        client->write_data(vector< uint8_t >(parkinglot.temperature, parkinglot.temperature + sizeof(parkinglot.temperature)));
        // 发送湿度
        client->write_data(vector< uint8_t >(parkinglot.humidity, parkinglot.humidity + sizeof(parkinglot.humidity)));
        // 发送海拔
        client->write_data(vector< uint8_t >(parkinglot.altitude, parkinglot.altitude + sizeof(parkinglot.altitude)));
        // 发送气压
        client->write_data(vector< uint8_t >(parkinglot.pressure, parkinglot.pressure + sizeof(parkinglot.pressure)));
        // 发送烟雾浓度
        client->write_data(vector< uint8_t >(parkinglot.concentration, parkinglot.concentration + sizeof(parkinglot.concentration)));
        // 发送烟雾阈值
        client->write_data(vector< uint8_t >(parkinglot.threshold, parkinglot.threshold + sizeof(parkinglot.threshold)));
        // 发送光照强度
        client->write_data(vector< uint8_t >(parkinglot.illumination, parkinglot.illumination + sizeof(parkinglot.illumination)));
        // 发送车位总数
        client->write_data(vector< uint8_t >(parkinglot.total, parkinglot.total + sizeof(parkinglot.total)));
        // 发送车位剩余
        client->write_data(vector< uint8_t >(parkinglot.remainder, parkinglot.remainder + sizeof(parkinglot.remainder)));
        // 2s发送一次
        sleep(2);
    }
    pthread_exit(NULL);
    return NULL;
}

int main(int argc, char *argv[]) {
    // 打印参数
    printf("argv[%d]: ", argc);
    for (int i = 1; i < argc; i++)
        printf("%s ", argv[i]);
    printf("\n");

    int32_t num;
    pthread_t tid;
    uint8_t _nums[] = {8, 9};
    Screen::POINT point = {0, 0};
    Screen::TOUCHEVENT touchEvent;
    vector< uint8_t > nums(_nums, _nums + sizeof(_nums));
    int32_t lamp = 0, railing = 0, camera = 0, threshold = 50, distance = 50, total = 50, remainder = 50;
    Screen screen(LED_DEV, 800, 480);                  // 屏幕初始化
    Smoke smoke("/dev/ttySAC2", 9600);                 // 烟雾初始化
    Led led("/dev/led_drv", nums, LED_OFF);            // led初始化
    Ultrasonic ultrasonic("/dev/ttySAC1", 9600);       // 超声初始化
    Environment environment("/dev/ttySAC3", 9600);     // 环境初始化
    Client client("47.98.153.253", stoi(argv[1]), 32); // 服务初始化
    printf("success!\n");
    // 创建线程
    pthread_create(&tid, NULL, main_thread, &client);
    // 清除背景
    screen.draw_fill(point, 800, 480, 0xffffff);
    // 加载触摸
    screen.load_touch("/dev/input/event0");
    // 加载背景
    screen.load_bmp("./background.bmp").draw_bmp(0, 0, 800, 480, 0, 0, 800, 480, 0xff000000);
    // 标题
    screen.draw_words("智慧停车场系统", 289, 5, 32, 32, 5, 5, 0x00000000);
    // 信息第一列
    screen.draw_words("烟雾浓度", 10, 50, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("烟雾阈值", 10, 100, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("光照强度", 10, 150, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("车位总数", 10, 200, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("车位剩余", 10, 250, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("灯\t\t", 10, 300, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("栏杆\t", 10, 350, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("摄像头 ", 10, 400, 28, 28, 2, 2, 0x00000000);
    // 信息第二列
    screen.draw_words("距离", 410, 50, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("温度", 410, 100, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("湿度", 410, 150, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("海拔", 410, 200, 28, 28, 2, 2, 0x00000000);
    screen.draw_words("气压", 410, 250, 28, 28, 2, 2, 0x00000000);
    // 主循环
    while (1) {
        // 清除背景
        screen.draw_fill(point, 800, 480, 0xffffff);
        // 加载背景
        screen.load_bmp("./background.bmp").draw_bmp(0, 0, 800, 480, 0, 0, 800, 480, 0xff000000);
        // 标题
        screen.draw_words("智慧停车场系统", 289, 5, 32, 32, 5, 5, 0x00000000);
        // 信息第一列
        screen.draw_words("烟雾浓度", 10, 50, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("烟雾阈值", 10, 100, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("光照强度", 10, 150, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("车位总数", 10, 200, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("车位剩余", 10, 250, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("灯\t\t", 10, 300, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("栏杆\t", 10, 350, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("摄像头 ", 10, 400, 28, 28, 2, 2, 0x00000000);
        // 信息第二列
        screen.draw_words("距离", 410, 50, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("温度", 410, 100, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("湿度", 410, 150, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("海拔", 410, 200, 28, 28, 2, 2, 0x00000000);
        screen.draw_words("气压", 410, 250, 28, 28, 2, 2, 0x00000000);
        // 灯
        parkinglot.lamp[0] = 0x1;
        copy(parkinglot.lamp + 1, lamp, sizeof(parkinglot.lamp - 1));
        num = *(int32_t *)(parkinglot.lamp + 1);
        screen.draw_words(lamp == 0 ? "开" : "关", 133, 300, 28, 28, 2, 2, 0x00000000);
        printf("lamp:%.0f\n", num);

        // 栏杆
        parkinglot.railing[0] = 0x2;
        copy(parkinglot.railing + 1, railing, sizeof(parkinglot.railing - 1));
        num = *(int32_t *)(parkinglot.railing + 1);
        screen.draw_words(railing == 0 ? "抬" : "放", 133, 350, 28, 28, 2, 2, 0x00000000);
        printf("railing:%.0f\n", num);

        // 摄像头
        parkinglot.camera[0] = 0x3;
        copy(parkinglot.camera + 1, camera, sizeof(parkinglot.camera - 1));
        num = *(int32_t *)(parkinglot.camera + 1);
        screen.draw_words(camera == 0 ? "开" : "关", 133, 400, 28, 28, 2, 2, 0x00000000);
        printf("camera:%.0f\n", num);

        // 距离
        parkinglot.distance[0] = 0x4;
        copy(parkinglot.distance + 1, ultrasonic.get_distance(), sizeof(parkinglot.distance - 1));
        num = *(int32_t *)(parkinglot.distance + 1);
        screen.draw_nums(1.0 * num / 10, 473, 50, 28, 28, 2, 2, 2, 0x00000000);
        printf("distance:%.2f\n", 1.0 * num / 10);
        if (num < distance) {
            if (remainder > 0) {
                railing = 0;
                remainder -= 1;
            }
        } else
            railing = 1;

        // 温度
        parkinglot.temperature[0] = 0x5;
        copy(parkinglot.temperature + 1, environment.get_temperature(), sizeof(parkinglot.temperature - 1));
        num = *(int32_t *)(parkinglot.temperature + 1);
        screen.draw_nums(1.0 * num / 100, 473, 100, 28, 28, 2, 2, 2, 0x00000000);
        printf("temperature:%.2f\n", 1.0 * num / 100);

        // 湿度
        parkinglot.humidity[0] = 0x6;
        copy(parkinglot.humidity + 1, environment.get_humidity(), sizeof(parkinglot.humidity - 1));
        num = *(int32_t *)(parkinglot.humidity + 1);
        screen.draw_nums(1.0 * num / 100, 473, 150, 28, 28, 2, 2, 2, 0x00000000);
        printf("humidity:%.2f\n", 1.0 * num / 100);

        // 海拔
        parkinglot.altitude[0] = 0x7;
        copy(parkinglot.altitude + 1, environment.get_altitude(), sizeof(parkinglot.altitude - 1));
        num = *(int32_t *)(parkinglot.altitude + 1);
        screen.draw_nums(num, 473, 200, 28, 28, 0, 2, 2, 0x00000000);
        printf("altitude:%.0f\n", num);

        // 气压
        parkinglot.pressure[0] = 0x8;
        copy(parkinglot.pressure + 1, environment.get_pressure(), sizeof(parkinglot.pressure - 1));
        num = *(int32_t *)(parkinglot.pressure + 1);
        screen.draw_nums(1.0 * num / 100, 473, 250, 28, 28, 0, 2, 2, 0x00000000);
        printf("pressure:%.2f\n", 1.0 * num / 100);

        // 烟雾浓度
        parkinglot.concentration[0] = 0x9;
        copy(parkinglot.concentration + 1, smoke.get_concentration(), sizeof(parkinglot.concentration - 1));
        num = *(int32_t *)(parkinglot.concentration + 1);
        screen.draw_nums(num, 133, 50, 28, 28, 0, 2, 2, 0x00000000);
        printf("concentration:%.0f\n", num);
        if (num < threshold)
            led.set_state(8, LED_OFF);
        else
            led.set_state(8, LED_ON);

        // 烟雾阈值
        parkinglot.threshold[0] = 0xa;
        copy(parkinglot.threshold + 1, threshold, sizeof(parkinglot.threshold - 1));
        num = *(int32_t *)(parkinglot.threshold + 1);
        screen.draw_nums(num, 133, 100, 28, 28, 0, 2, 2, 0x00000000);
        printf("threshold:%.0f\n", num);

        // 光照强度
        parkinglot.illumination[0] = 0xb;
        copy(parkinglot.illumination + 1, environment.get_lightIntensity(), sizeof(parkinglot.illumination - 1));
        num = *(int32_t *)(parkinglot.illumination + 1);
        screen.draw_nums(1.0 * num / 100, 133, 150, 28, 28, 0, 2, 2, 0x00000000);
        printf("illumination:%.0f\n", 1.0 * num / 100);

        // 车位总数
        parkinglot.total[0] = 0xc;
        copy(parkinglot.total + 1, total, sizeof(parkinglot.total - 1));
        num = *(int32_t *)(parkinglot.total + 1);
        screen.draw_nums(num, 133, 200, 28, 28, 0, 2, 2, 0x00000000);
        printf("total:%.0f\n", num);

        // 车位剩余
        parkinglot.remainder[0] = 0xd;
        copy(parkinglot.remainder + 1, remainder, sizeof(parkinglot.remainder - 1));
        num = *(int32_t *)(parkinglot.remainder + 1);
        screen.draw_nums(num, 133, 250, 28, 28, 0, 2, 2, 0x00000000);
        printf("total:%.0f\n", num);

        // 获取触摸
        touchEvent = screen.get_touch();
        // 滑动事件
        if (touchEvent.type == EVENT_SLIDE) {
            // 烟雾阈值+
            if (touchEvent.startY < touchEvent.endY && abs(touchEvent.endY - touchEvent.startY) > abs(touchEvent.endX - touchEvent.startX)) {
                threshold += 5;
                if (threshold > 1000)
                    threshold = 1000;
            }
            // 烟雾阈值-
            if (touchEvent.startY > touchEvent.endY && abs(touchEvent.endY - touchEvent.startY) > abs(touchEvent.endX - touchEvent.startX)) {
                threshold -= 5;
                if (threshold < 0)
                    threshold = 0;
            }
            // 距离+
            if (touchEvent.startX < touchEvent.endX && abs(touchEvent.endY - touchEvent.startY) < abs(touchEvent.endX - touchEvent.startX)) {
                distance += 5;
                if (distance > 1000)
                    distance = 1000;
            }
            // 距离-
            if (touchEvent.startX > touchEvent.endX && abs(touchEvent.endY - touchEvent.startY) < abs(touchEvent.endX - touchEvent.startX)) {
                distance -= 5;
                if (distance < 0)
                    distance = 0;
            }
        }
        // 点击事件
        if (touchEvent.type == EVENT_CLICK) {
            if (touchEvent.endX >= 133 && touchEvent.endX <= 183 && touchEvent.endY >= 300 && touchEvent.endY <= 328) {
                lamp = !lamp;
            }
            if (touchEvent.endX >= 133 && touchEvent.endX <= 211 && touchEvent.endY >= 400 && touchEvent.endY <= 428) {
                camera = !camera;
            }
            if (touchEvent.endX >= 133 && touchEvent.endX <= 183 && touchEvent.endY >= 250 && touchEvent.endY <= 278) {
                remainder += 1;
                if (remainder > total)
                    remainder = total;
            }
        }
        sleep(1);
    };
    return 0;
}